
package org.zn.note.designpattern;

import java.util.Arrays;

/**
 * 抽象工厂模式（Abstract Factory Pattern）
 * 工厂的工厂，抽象工厂生成产品簇工厂，然后产品簇工厂生成具体的实例对象。
 */
public class Pattern02_AbstractFactory {

    public static void main(String[] args) {
        Arrays.asList("CIRCLE", "RECTANGLE", "SQUARE").stream().forEach(
                type -> FactoryProducer
                        .getFactory("SHAPE") // 先获取创建SHAPE实例的工厂实例
                        .getShape(type) // 再用获取的工厂实例，来创建对象
                        .draw());
        Arrays.asList("RED", "Green", "BLUE").stream().forEach(
                type -> FactoryProducer.getFactory("COLOR").getColor(type).fill());
    }

    // 有一个抽象方法
    private static abstract class AbstractFactory {
        public abstract Color getColor(String color);

        public abstract Pattern01_Factory.Shape getShape(String shape); // 复用工厂模式中的图形
    }

    private static class FactoryProducer {
        static AbstractFactory getFactory(String choice) {
            if (choice.equalsIgnoreCase("SHAPE")) {
                return new ShapeFactory();
            } else if (choice.equalsIgnoreCase("COLOR")) {
                return new ColorFactory();
            }
            return null;
        }
    }

    private static class ShapeFactory extends AbstractFactory {
        @Override
        public Pattern01_Factory.Shape getShape(String shapeType) {
            if (shapeType == null) {
                return null;
            }
            if (shapeType.equalsIgnoreCase("CIRCLE")) {
                return new Pattern01_Factory.Circle();
            } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
                return new Pattern01_Factory.Rectangle();
            } else if (shapeType.equalsIgnoreCase("SQUARE")) {
                return new Pattern01_Factory.Square();
            }
            return null;
        }

        @Override
        public Color getColor(String color) {
            return null;
        }
    }

    private static class ColorFactory extends AbstractFactory {
        @Override
        public Pattern01_Factory.Shape getShape(String shapeType) {
            return null;
        }

        @Override
        public Color getColor(String color) {
            if (color == null) {
                return null;
            }
            if (color.equalsIgnoreCase("RED")) {
                return new Red();
            } else if (color.equalsIgnoreCase("GREEN")) {
                return new Green();
            } else if (color.equalsIgnoreCase("BLUE")) {
                return new Blue();
            }
            return null;
        }
    }

    interface Color {
        void fill();
    }

    static class Red implements Color {
        @Override
        public void fill() {
            System.out.println("Inside Red::fill() method.");
        }
    }

    static class Green implements Color {
        @Override
        public void fill() {
            System.out.println("Inside Green::fill() method.");
        }
    }

    static class Blue implements Color {
        @Override
        public void fill() {
            System.out.println("Inside Blue::fill() method.");
        }
    }
}
